using Engine;
using Game;
using GameEntitySystem;
using Random = Game.Random;

namespace SCIENEW {
    public class FlaxNBlockBehavior : NormalBlockBehavior, IUpdateable {
        public SubsystemTerrain m_subsystemTerrain;
        public SubsystemGameInfo m_subsystemGameInfo;
        public SubsystemTime m_subsystemTime;

        public Dictionary<Point3, Placement> m_toUpdate = [];

        public struct Placement(int value, Point3 owner) {
            public int Value = value;
            public Point3 Owner = owner;
        }

        public UpdateOrder UpdateOrder => UpdateOrder.Default;

        Random m_random = new();

        public FlaxNBlockBehavior(Project project) : base(project) {
            m_subsystemTerrain = project.FindSubsystem<SubsystemTerrain>(true);
            m_subsystemGameInfo = project.FindSubsystem<SubsystemGameInfo>(true);
            m_subsystemTime = project.FindSubsystem<SubsystemTime>(true);
        }

        public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ) {
            int cellValue = m_subsystemTerrain.Terrain.GetCellValue(x, y - 1, z);
            int cellContent = Terrain.ExtractContents(cellValue);
            if (cellContent != GrassBlock.Index
                && cellContent != DirtBlock.Index
                && cellContent != SoilBlock.Index
                && NormalBlockManager.GetNormalBlock(cellValue) is not FlaxNBlock) {
                m_subsystemTerrain.DestroyCell(
                    0,
                    x,
                    y,
                    z,
                    0,
                    noDrop: false,
                    noParticleSystem: false
                );
            }
        }

        public override void OnPoll(int value, int x, int y, int z, int pollPass) {
            if (m_subsystemGameInfo.WorldSettings.EnvironmentBehaviorMode != 0) {
                return;
            }
            int cellValue = m_subsystemTerrain.Terrain.GetCellValue(x, y + 1, z);
            if (Terrain.ExtractLight(cellValue) >= 12 && m_random.Float(0f, 1f) < 0.5f) {//亚麻方块头上光照充足
                int flaxValue = m_subsystemTerrain.Terrain.GetCellValueFast(x, y, z);
                int flaxValueB1 = m_subsystemTerrain.Terrain.GetCellValueFast(x, y - 1, z);
                int flaxValueB2 = m_subsystemTerrain.Terrain.GetCellValueFast(x, y - 2, z);
                switch (NormalBlockManager.GetNormalBlockCraftingID(flaxValue)) {
                    case "Flax_Top": //亚麻顶端
                        if (Terrain.ExtractContents(cellValue) == AirBlock.Index
                            && NormalBlockManager.GetNormalBlock(flaxValueB2) is not FlaxNBlock) {//头顶是空气，并且没有长超过3格高
                            m_toUpdate.Add(new Point3(x, y, z), new Placement(NormalBlockManager.GetNormalBlockID("Flax_Stem"), new Point3(x, y, z)));//自己变成茎秆
                            m_toUpdate.Add(new Point3(x, y + 1, z), new Placement(NormalBlockManager.GetNormalBlockID("Flax_Top"), new Point3(x, y, z)));//向上长一格
                        }
                        break;
                    case "Flax_Stem_Ripened":
                        break;
                    case "Flax_Stem"://亚麻茎秆
                        m_toUpdate.Add(new Point3(x, y, z), new Placement(NormalBlockManager.GetNormalBlockID("Flax_Stem_Ripened"), new Point3(x, y, z)));//自己成熟
                        break;
                }
            }
        }

        //防止亚麻破坏后还继续生长
        public override void OnBlockRemoved(int value, int newValue, int x, int y, int z) {
            foreach (KeyValuePair<Point3, Placement> item in m_toUpdate) {
                if (item.Value.Owner == new Point3(x, y, z)) {
                    m_toUpdate.Remove(item.Key);
                }
            }
        }

        public void Update(float dt) {
            if (m_subsystemTime.PeriodicGameTimeEvent(60.0, 0.0)) {
                foreach (KeyValuePair<Point3, Placement> item in m_toUpdate) {
                    m_subsystemTerrain.ChangeCell(item.Key.X, item.Key.Y, item.Key.Z, item.Value.Value);
                }
                m_toUpdate.Clear();
            }
        }
    }
}